package arrays;

/**
 * @author pengfei.hpf
 * @date 2020/3/15
 * @verdion 1.0.0
 * 面试题40. 最小的k个数
 * 输入整数数组 arr ，找出其中最小的 k 个数。例如，输入4、5、1、6、2、7、3、8这8个数字，则最小的4个数字是1、2、3、4。
 *
 *
 *
 * 示例 1：
 *
 * 输入：arr = [3,2,1], k = 2
 * 输出：[1,2] 或者 [2,1]
 * 示例 2：
 *
 * 输入：arr = [0,1,2,1], k = 1
 * 输出：[0]
 *
 *
 * 限制：
 *
 * 0 <= k <= arr.length <= 10000
 * 0 <= arr[i] <= 10000
 */
public class GetLeastNumbers {
    public int[] getLeastNumbers(int[] arr, int k) {
        if(arr == null || arr.length == 0){
            return arr;
        }
        if(k == 0){
            return new int[0];
        }
        int index = partition(arr, 0, arr.length - 1);
        //TODO: partition的时候要记录下来开头和结尾!!
        int start = 0;
        int end = arr.length - 1;
        while(index != k - 1){
            if(index > k - 1){
                end = index - 1;
                index = partition(arr, start, end);
            } else {
                start = index + 1;
                index = partition(arr, start, end);
            }
        }
        int[] res = new int[k];
        for(int i = 0; i < k; i ++){
            res[i] = arr[i];
        }
        return res;
    }

    private int partition(int[] arr, int start, int end){
        int p = arr[end];
        int small = start - 1;
        for(int i = start; i < end; i ++){
            if(arr[i] < p){
                small ++;
                if(small != i){
                    swap(arr, small, i);
                }
            }
        }
        small ++;
        if(small != end){
            swap(arr, small, end);
        }
        return small;
    }

    private void swap(int[] arr, int i, int j){
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    public static void main(String[] args){
        System.out.println(new GetLeastNumbers().getLeastNumbers(new int[]{0,0,1,2,4,2,2,3,1,4}, 8));

    }
}
